package nl.grol.yakshop.web.filter;

import java.io.IOException;
import java.util.Map;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import nl.grol.yakshop.util.PMF;
import nl.grol.yakshop.web.util.RequestContext;
import nl.grol.yakshop.web.util.RequestContextHolder;

import com.google.inject.Singleton;

@Singleton
public class RequestEnrichingFilter implements Filter {
	private static final Logger LOGGER = Logger.getLogger(RequestEnrichingFilter.class.getName());

	@Override
	public void init(FilterConfig config) throws ServletException {
	}

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest req, ServletResponse resp,
			FilterChain chain) throws IOException, ServletException {
		boolean doInjectContext = false;
		
	    RequestContext requestContext = null;
		PersistenceManager pm = null;

		
		String url = ((HttpServletRequest)req).getRequestURI();
		if( url.endsWith( ".js" )   == false &&
		    url.endsWith( ".html" ) == false &&
		    url.endsWith( ".png" )  == false &&
		    url.endsWith( ".gif" )  == false &&
		    url.endsWith( ".ico" )  == false &&
		    url.endsWith( ".css" )  == false ) 
		{
			doInjectContext = true;
		}
		
		if( doInjectContext == true ) {
			logRequest((HttpServletRequest)req);
    		try {
    		    
    	        LOGGER.fine( "Acquire request specific context for url: " + 
    	        		((HttpServletRequest)req).getRequestURI() );
    	        
    			// create Persistance reactionCreator
                pm = PMF.get().getPersistenceManager();
    	        requestContext = new RequestContext( pm );
    
    			// add the thread local context
    			RequestContextHolder.setContext( requestContext );
    			
    			// forward
    			chain.doFilter(req, resp);
    			
   			
    		} finally {
    		
    			if( requestContext != null ) {
    			    LOGGER.info( "*** Persistance stats: numReads:" + requestContext.getReadCounter() + 
    			    		        " numUpdates;" + requestContext.getWriteCounter() + "***");
    			}
    			
    			
    			if( pm != null && pm.isClosed() == false ) {
    				pm.close();
    			}

    			// get rid of thread context
    			RequestContextHolder.removeContext();
    			
    		}
		} else {
			chain.doFilter(req, resp);

		}
	}
	
	private static void logRequest(HttpServletRequest req) {
		StringBuffer sb = new StringBuffer();
		
		@SuppressWarnings("unchecked")
		Map<String, String[]> map = (Map<String, String[]>) req.getParameterMap();
		for (Map.Entry<String, String[]> entry : map.entrySet()) {
			String[] values = entry.getValue();
			for (String value : values) {
				sb.append(entry.getKey() + "='" + value +"', ");
			}
		}
		LOGGER.info( req.getMethod() + " on " + req.getRequestURI() + 
				" with params " + sb.toString() );
	}
}
